/***************************************************
 * ccp903_cards.c
 *
 * Created on: Mar 20, 2019
 * Author: zjjin@ccore.com
 ***************************************************/

#include "./INCLUDE/compate.h"
#include "./INCLUDE/pci_csec.h"
#include "./INCLUDE/desc.h"
#include "./INCLUDE/desc_constr.h"
#include "./INCLUDE/sym_perf.h"
#include <linux/random.h>

void sm1_stand_test(void)
{
	int i,ret;

	u8 key[32]={
		0xE3,0x83,0x0F,0x2F,0xF5,0x87,0x7D,0xAD,0x19,0x41,0x75,0x7B,0x17,0xB5,0xE3,0x92,
		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	};
	u8 iv[16] = {
		/* IV 1 for key 3 */
		0x38,0x32,0xF2,0x7E,0x0A,0x14,0x51,0xAF,0x4B,0x97,0x47,0xA0,0x17,0x7C,0xDF,0xC2
	};

	u8 data[32]={
		0x63,0x36,0x3D,0x95,0xAC,0x94,0x46,0x28,0x29,0x2D,0xB1,0x2F,0x6B,0x39,0x37,0x5C,
		0x66,0x17,0x94,0x6A,0xFC,0xC2,0x73,0x14,0xE5,0xA9,0x4B,0x59,0xA1,0x98,0xCC,0x33
	};

	u8 stdout[32]={
		0xC6,0x2A,0xC6,0xF7,0x8E,0xEF,0xFE,0x46,0x71,0x20,0x06,0x5B,0x84,0x36,0xB7,0xDF,
		0xA8,0x63,0xAB,0x9F,0x73,0xC0,0x4B,0xBE,0x9D,0xAE,0x78,0xE5,0x92,0x09,0x71,0x01,
	};
	
	u8 dout[32];
	
	printk(KERN_ERR "sm1 stand test start!\n");
	ret = sm1_cbc_encrypt_newapi(data,dout,32,key,iv);
	if(ret)
	{
		printk(KERN_ERR "sm1 stand test fail,hard error!\n");
		return ;
	}

	for(i=0;i<32;i++)
	{
		if(dout[i]!=stdout[i])
		{
			printk(KERN_ERR "sm1 stand test fail,std compare error!\n");
			return;
		}

	}
	printk(KERN_ERR "sm1 stand test ok,std compare ok!\n");
}

void sm3_stand_test(void)
{
	int i,ret;
	u8 out[32];

	u8 hmac_key[] = {
		0x11,0x22,0x33,0x44,0x55,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	};

	u8 data[] = {
		0x2C,0xB6,0xA0,0x6E,0x92,0xDC,0x95,0x70,0x24,0x2E,0x4E,0x77,0xA1,0x8D,0x6D,0xF0,
		0xBF,0xA1,0x63,0xB7,0x33,0xA6,0x81,0xDF,0xA8,0x6F,0x48,0x65,0x0A,0x25,0x1F,0x76,
	};
	/*
	u8 hash_stdout[]={
		0x8E,0xD6,0xCD,0xEC,0x55,0x96,0xEA,0x9B,0x57,0x7A,0x19,0x5E,0x0A,0x41,0x9F,0xD9,
		0xFD,0x40,0x2C,0xCF,0x8B,0x11,0xB5,0x47,0xEC,0x99,0xAC,0xEE,0x81,0xB4,0xF4,0x88,		
	};
	*/
	u8 hmac_stdout[]={
		0x17,0xe3,0x2b,0xad,0x10,0x4d,0xeb,0x3e,0xf8,0xfc,0xf4,0xfb,0xa2,0xba,0x92,0xcf,
		0xc5,0x83,0xea,0xc8,0x70,0x9a,0xb8,0x64,0xd9,0xaa,0x6d,0xd8,0xe2,0x15,0xec,0x4c,
	};

	printk(KERN_ERR "sm3 stand test start!\n");
	ret = sm3_hmac_newapi(hmac_key,6,data,32,out);
	if(ret)
		printk(KERN_ERR "sm3_hmac stand test error\n");


	for(i=0;i<32;i++)
	{
		
		if(out[i]!=hmac_stdout[i])
		{
			printk(KERN_ERR "hmac(sm3) stand test fail,std compare error!\n");
			return;
		}

	}

	printk(KERN_ERR "hmac(sm3) stand test ok!\n");
	return;
}
void sm3_stand_test_asyn_recovery(void)
{
	int i,ret;
	u8 out[32];

	u8 hmac_key[] = {
		0x11,0x22,0x33,0x44,0x55,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	};

	u8 data[] = {
		0x2C,0xB6,0xA0,0x6E,0x92,0xDC,0x95,0x70,0x24,0x2E,0x4E,0x77,0xA1,0x8D,0x6D,0xF0,
		0xBF,0xA1,0x63,0xB7,0x33,0xA6,0x81,0xDF,0xA8,0x6F,0x48,0x65,0x0A,0x25,0x1F,0x76,
	};
	/*
	u8 hash_stdout[]={
		0x8E,0xD6,0xCD,0xEC,0x55,0x96,0xEA,0x9B,0x57,0x7A,0x19,0x5E,0x0A,0x41,0x9F,0xD9,
		0xFD,0x40,0x2C,0xCF,0x8B,0x11,0xB5,0x47,0xEC,0x99,0xAC,0xEE,0x81,0xB4,0xF4,0x88,		
	};
	*/
	u8 hmac_stdout[]={
		0x17,0xe3,0x2b,0xad,0x10,0x4d,0xeb,0x3e,0xf8,0xfc,0xf4,0xfb,0xa2,0xba,0x92,0xcf,
		0xc5,0x83,0xea,0xc8,0x70,0x9a,0xb8,0x64,0xd9,0xaa,0x6d,0xd8,0xe2,0x15,0xec,0x4c,
	};

	printk(KERN_ERR "sm3 stand test start!\n");
	ret = sm3_hmac_newapi_asyn_recovery(hmac_key,6,data,32,out);
	if(ret)
		printk(KERN_ERR "sm3_hmac stand test error\n");


	for(i=0;i<32;i++)
	{
		
		if(out[i]!=hmac_stdout[i])
		{
			printk(KERN_ERR "hmac(sm3) stand test fail,std compare error!\n");
			return;
		}

	}

	printk(KERN_ERR "hmac(sm3) stand test ok!\n");
	return;
}
#define KCAPI_DLEN 0x41810
// #define KCAPI_DLEN 0x410
int sm1_simple_test(void)
{
	int i;
	int ret;
	u8 key[48],ive[16],ivd[16],*pt,*ct;
	int inlen = KCAPI_DLEN;

	pt = (u8 *)kmalloc(KCAPI_DLEN,GFP_KERNEL);
	ct = (u8 *)kmalloc(KCAPI_DLEN,GFP_KERNEL);

	for(i=0;i<16;i++)
	{
		ive[i] = i+1;
		ivd[i] = i+1;
	}
	for(i=0;i<48;i++)
	{
		key[i]=i;
	}
	for(i=0;i<KCAPI_DLEN;i++)
	{
		pt[i] = i&0xff;
	}

	printk(KERN_ERR "sm1 simple test start!\n");

	ret = sm1_cbc_encrypt_newapi(pt,ct,inlen,key,ive);
	if(ret)
	{
		printk(KERN_ERR "sm1 simple test fail,enc error!\n");
		return -1;
	}
	
	for(i=0;i<KCAPI_DLEN;i++)
	{
		pt[i] = 0;
	}

	ret = sm1_cbc_decrypt_newapi(ct,pt,inlen,key,ivd);
	if(ret)
	{
		printk(KERN_ERR "sm1 simple test fail,dec error!\n");
		return -2;
	}

	for(i=0;i<KCAPI_DLEN;i++)
	{
		if(pt[i]!= (i&0xff))
		{
			printk(KERN_ERR "sm1 simple test fail,enc then dec compare error!\n");
			return -3;
		}
	}

	printk(KERN_ERR "sm1 simple test ok,enc then dec compare ok!\n");

	kfree(pt);
	kfree(ct);

	return 0;
}

void sm1_stand_test_asyn_recovery(void)
{
	int i,ret;

	u8 key[32]={
		0xE3,0x83,0x0F,0x2F,0xF5,0x87,0x7D,0xAD,0x19,0x41,0x75,0x7B,0x17,0xB5,0xE3,0x92,
		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	};
	u8 iv[16] = {
		/* IV 1 for key 3 */
		0x38,0x32,0xF2,0x7E,0x0A,0x14,0x51,0xAF,0x4B,0x97,0x47,0xA0,0x17,0x7C,0xDF,0xC2
	};

	u8 data[32]={
		0x63,0x36,0x3D,0x95,0xAC,0x94,0x46,0x28,0x29,0x2D,0xB1,0x2F,0x6B,0x39,0x37,0x5C,
		0x66,0x17,0x94,0x6A,0xFC,0xC2,0x73,0x14,0xE5,0xA9,0x4B,0x59,0xA1,0x98,0xCC,0x33
	};

	u8 stdout[32]={
		0xC6,0x2A,0xC6,0xF7,0x8E,0xEF,0xFE,0x46,0x71,0x20,0x06,0x5B,0x84,0x36,0xB7,0xDF,
		0xA8,0x63,0xAB,0x9F,0x73,0xC0,0x4B,0xBE,0x9D,0xAE,0x78,0xE5,0x92,0x09,0x71,0x01,
	};
	
	u8 dout[32];
	
	printk(KERN_ERR "sm1 stand test start!\n");

	ret = sm1_cbc_encrypt_newapi_asyn_recovery(data,dout,32,key,iv);

	if(ret)
	{
		printk(KERN_ERR "sm1 stand test fail,hard error!\n");
		return ;
	}
	
	for(i=0;i<32;i++)
	{
		if(dout[i]!=stdout[i])
		{
			printk(KERN_ERR "sm1 stand test fail,std compare error!\n");
			return;
		}

	}
	printk(KERN_ERR "sm1 stand test ok,std compare ok!\n");
	return;
}

void sm4_stand_test_asyn_recovery_key_in_ram(void)
{
	int i,ret;

	/*u8 key[32]={
		0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16
	};*/
	
	unsigned int key = 0xE0370000;
	
	u8 iv[16] = {
		/* IV 1 for key 3 */
		0x38,0x32,0xF2,0x7E,0x0A,0x14,0x51,0xAF,0x4B,0x97,0x47,0xA0,0x17,0x7C,0xDF,0xC2
	};

	u8 data[32]={
		0x63,0x36,0x3D,0x95,0xAC,0x94,0x46,0x28,0x29,0x2D,0xB1,0x2F,0x6B,0x39,0x37,0x5C,
		0x66,0x17,0x94,0x6A,0xFC,0xC2,0x73,0x14,0xE5,0xA9,0x4B,0x59,0xA1,0x98,0xCC,0x33
	};

	u8 stdout[32]={
		0x39,0x59,0x6D,0x0C,0x93,0x81,0xF6,0x89,0xDD,0x25,0x75,0xE1,0x99,0xD3,0xC6,0xDF,
		0x4F,0x14,0x46,0xF2,0x3F,0x0F,0x4E,0x09,0xEB,0xC2,0x76,0x96,0x03,0x2A,0xB1,0xDE
	};
	
	u8 dout[32];
	
	printk(KERN_ERR "sm4 stand test start!\n");

	ret = sm4_ecb_encrypt_newapi_asyn_recovery_key_in_ram(data,dout,32,key,iv);

	if(ret)
	{
		printk(KERN_ERR "sm4 stand test fail,hard error!\n");
		return ;
	}
	

	for(i=0;i<32;i++)
	{
		if(dout[i]!=stdout[i])
		{
			printk(KERN_ERR "sm4 stand test fail,std compare error!\n");
			return;
		}

	}
	
	printk(KERN_ERR "sm1 stand test ok,std compare ok!\n");
	return;
}

int sm1_simple_test_asyn_recovery(void)
{

	int i;
	int ret;
	u8 key[48],ive[16],ivd[16],*pt,*ct;
	int inlen = KCAPI_DLEN;

	pt = (u8 *)kmalloc(KCAPI_DLEN,GFP_KERNEL);
	ct = (u8 *)kmalloc(KCAPI_DLEN,GFP_KERNEL);
	for(i=0;i<16;i++)
	{
		ive[i] = i+1;
		ivd[i] = i+1;
	}
	for(i=0;i<48;i++)
	{
		key[i]=i;
	}
	for(i=0;i<KCAPI_DLEN;i++)
	{
		pt[i] = i&0xff;
	}

	printk(KERN_ERR "sm1 simple test start!\n");
	ret = sm1_cbc_encrypt_newapi_asyn_recovery(pt,ct,inlen,key,ive);
	if(ret)
	{
		printk(KERN_ERR "sm1 simple test fail,enc error!\n");
		return -1;
	}
	
	for(i=0;i<KCAPI_DLEN;i++)
	{
		pt[i] = 0;
	}
	ret = sm1_cbc_decrypt_newapi_asyn_recovery(ct,pt,inlen,key,ivd);
	if(ret)
	{
		printk(KERN_ERR "sm1 simple test fail,dec error!\n");
		return -2;
	}
	for(i=0;i<KCAPI_DLEN;i++)
	{
		if(pt[i]!= (i&0xff))
		{
			printk(KERN_ERR "sm1 simple test fail,enc then dec compare error!\n");
			return -3;
		}
	}
	printk(KERN_ERR "sm1 simple test ok,enc then dec compare ok!\n");


	kfree(pt);
	kfree(ct);
	return 0;
}

struct timespec mytime;

void mytime_init(void)
{
	mytime.tv_sec = 0;
	mytime.tv_nsec = 0;
	return;
}

struct timespec mytime_on(void)
{
	struct timespec tv;
	getnstimeofday(&tv);
	return tv;
}

void mytime_off(struct timespec tv)
{
	struct timespec tvnow;
	getnstimeofday(&tvnow);
	mytime.tv_sec += tvnow.tv_sec-tv.tv_sec;
	mytime.tv_nsec += tvnow.tv_nsec - tv.tv_nsec;
	return;
}

int mytime_c(void)
{
	int time;
	time = mytime.tv_sec *1000000 +mytime.tv_nsec; 
	return time;
}

int snoop_newapi_speed(char *mstring,u8 alg,u8 type,u8 opt,int datasize,int keysize,int ivsize,u8 alg2,u8 type2,u8 opt2,int keysize2)
{

	struct parm *mparm;
	
	struct task_struct *task[N_THREADS];
	
	int i,time,speed;

	struct timespec tv;

	printk(KERN_ERR "%s speed test start\n",mstring);
	
	malg = alg;	mdatasize = datasize; mtype = type;mopt = opt; mkeysize = keysize; mivsize = ivsize;

	malg2 = alg2;  mtype2 = type2;mopt2 = opt2; mkeysize2 = keysize2;

	mparm = kmalloc(sizeof(struct parm)*N_THREADS,GFP_KERNEL);

	mytime_init();
	for(i=0;i<N_THREADS;i++)
	{
		init_completion(&(mparm[i].w));
		init_completion(&(mparm[i].c));
	}

	for(i=0;i<N_THREADS;i++)
	{
		task[i] = kthread_create(snoop_newapi_speed_do,(void *)(&(mparm[i])),"snoop_speed");
		if(!IS_ERR(task[i]))
		{
			wake_up_process(task[i]);
		}
		else
		{
			return 0;
		}
	}

	wait_timeout_kcapi(100);

	tv = mytime_on();

	for(i=0;i<N_THREADS;i++)
	{
		complete(&(mparm[i].w));
	}
	for(i=0;i<N_THREADS;i++)
	{
		wait_for_completion_interruptible(&(mparm[i].c));
	}

	mytime_off(tv);
	time = mytime_c();
	speed = DO_NUM*N_THREADS*mdatasize/time;
	speed*=8;
	printk(KERN_ERR "%s,size is %d,speed is %dMbps,%d\n",mstring,mdatasize,speed,time);
	kfree(mparm);
	return 0;
}
int snoop_newapi_speed_asyn(char *mstring,u8 alg,u8 type,u8 opt,int datasize,int keysize,int ivsize,u8 alg2,u8 type2,u8 opt2,int keysize2)
{
	struct parm *mparm;
	struct task_struct *task[N_THREADS];
	int i;

	//printk(KERN_ERR "%s speed test start\n",mstring);
	malg = alg;	mdatasize = datasize; mtype = type;mopt = opt; mkeysize = keysize; mivsize = ivsize;
	malg2 = alg2;  mtype2 = type2;mopt2 = opt2; mkeysize2 = keysize2;
	mparm = kmalloc(sizeof(struct parm)*N_THREADS,GFP_KERNEL);

	mytime_init();
	for(i=0;i<N_THREADS;i++)
	{
		init_completion(&(mparm[i].w));
		init_completion(&(mparm[i].c));
	}

	for(i=0;i<N_THREADS;i++)
	{
		task[i] = kthread_create(snoop_newapi_speed_do_asyn,(void *)(&(mparm[i])),"snoop_speed");
		if(!IS_ERR(task[i]))
		{
			wake_up_process(task[i]);
		}
		else
		{
			return 0;
		}
	}

	wait_timeout_kcapi(100);

	for(i=0;i<N_THREADS;i++)
	{
		complete(&(mparm[i].w));
	}
	for(i=0;i<N_THREADS;i++)
	{
		wait_for_completion_interruptible(&(mparm[i].c));
	}

	kfree(mparm);
	return 0;
}
int snoop_sp_newapi_speed(char *mstring,u8 alg,u8 type,u8 opt,int datasize,int keysize,int ivsize,u8 alg2,u8 type2,u8 opt2,int keysize2,int ivsize2)
{

	struct parm *mparm;
	
	struct task_struct *task[N_THREADS];
	
	int i,time,speed;

	struct timespec tv;

	printk(KERN_ERR "%s speed test start\n",mstring);
	
	malg = alg;	mdatasize = datasize; mtype = type;mopt = opt; mkeysize = keysize; mivsize = ivsize;

	malg2 = alg2;  mtype2 = type2;mopt2 = opt2; mkeysize2 = keysize2; mivsize2 = ivsize2;

	mparm = kmalloc(sizeof(struct parm)*N_THREADS,GFP_KERNEL);

	mytime_init();
	for(i=0;i<N_THREADS;i++)
	{
		init_completion(&(mparm[i].w));
		init_completion(&(mparm[i].c));
	}

	for(i=0;i<N_THREADS;i++)
	{
		task[i] = kthread_create(snoop_sp_newapi_speed_do,(void *)(&(mparm[i])),"snoop_speed");
		if(!IS_ERR(task[i]))
		{
			wake_up_process(task[i]);
		}
		else
		{
			return 0;
		}
	}

	wait_timeout_kcapi(100);

	tv = mytime_on();

	for(i=0;i<N_THREADS;i++)
	{
		complete(&(mparm[i].w));
	}
	for(i=0;i<N_THREADS;i++)
	{
		wait_for_completion_interruptible(&(mparm[i].c));
	}

	mytime_off(tv);
	time = mytime_c();
	speed = DO_NUM*N_THREADS*mdatasize/time;
	speed*=8;
#ifdef ASYN_MODE_BENCHMARK
	printk(KERN_ERR "%s,size is %d,speed is %dMbps,%d\n",mstring,mdatasize,speed,time);
#else
	printk(KERN_ERR "%s function test done!\n",mstring);
#endif
	kfree(mparm);
	return 0;
}

int snoop_sp_newapi_speed_asyn(char *mstring,u8 alg,u8 type,u8 opt,int datasize,int keysize,int ivsize,u8 alg2,u8 type2,u8 opt2,int keysize2,int ivsize2)
{
	struct parm *mparm;
	struct task_struct *task[N_THREADS];
	int i;

	printk(KERN_ERR "%s speed test start\n",mstring);
	malg = alg;	mdatasize = datasize; mtype = type;mopt = opt; mkeysize = keysize; mivsize = ivsize;
	malg2 = alg2;  mtype2 = type2;mopt2 = opt2; mkeysize2 = keysize2; mivsize2 = ivsize2;
	mparm = kmalloc(sizeof(struct parm)*N_THREADS,GFP_KERNEL);

	mytime_init();
	for(i=0;i<N_THREADS;i++)
	{
		init_completion(&(mparm[i].w));
		init_completion(&(mparm[i].c));
	}

	for(i=0;i<N_THREADS;i++)
	{
		task[i] = kthread_create(snoop_sp_newapi_speed_do_asyn,(void *)(&(mparm[i])),"snoop_speed");
		if(!IS_ERR(task[i]))
		{
			wake_up_process(task[i]);
		}
		else
		{
			return 0;
		}
	}

	wait_timeout_kcapi(100);

	for(i=0;i<N_THREADS;i++)
	{
		complete(&(mparm[i].w));
	}
	for(i=0;i<N_THREADS;i++)
	{
		wait_for_completion_interruptible(&(mparm[i].c));
	}
	printk(KERN_ERR "%s function test done!\n",mstring);

	kfree(mparm);
	return 0;

}

int sym_newapi_speed(char *mstring,u8 alg,u8 type,u8 opt,int datasize,int keysize,int ivsize)
{

	struct parm *mparm;
	
	struct task_struct *task[N_THREADS];
	
	int i,time,speed;

	struct timespec tv;

	printk(KERN_ERR "%s speed test start\n",mstring);
	
	malg = alg;	mdatasize = datasize; mtype = type;mopt = opt; mkeysize = keysize; mivsize = ivsize;

	mparm = kmalloc(sizeof(struct parm)*N_THREADS,GFP_KERNEL);

	mytime_init();

	for(i=0;i<N_THREADS;i++)
	{
		init_completion(&(mparm[i].w));
		init_completion(&(mparm[i].c));
	}

	for(i=0;i<N_THREADS;i++)
	{
		task[i] = kthread_create(sym_newapi_speed_do,(void *)(&(mparm[i])),"sym_speed");
		if(!IS_ERR(task[i]))
		{
			wake_up_process(task[i]);
		}
		else
		{
			return 0;
		}
	}

	wait_timeout_kcapi(100);

	tv = mytime_on();

	for(i=0;i<N_THREADS;i++)
	{
		complete(&(mparm[i].w));
	}
	
    for(i=0;i<N_THREADS;i++)
	{
		wait_for_completion_interruptible(&(mparm[i].c));
	}

	mytime_off(tv);
	time = mytime_c();
	speed = DO_NUM*N_THREADS*mdatasize/time;
	speed*=8;
   
	kfree(mparm);

	printk(KERN_ERR "%s,size is %d,speed is %dMbps,%d\n",mstring,mdatasize,speed,time);
	return 0;
}

int sym_newapi_speed_asyn_recovery(char *mstring,u8 alg,u8 type,u8 opt,int datasize,int keysize,int ivsize)
{

	struct parm *mparm;
	
	struct task_struct *task[N_THREADS];
	
	int i,j;
	uint32_t time,speed;

	struct timespec tv;

	malg = alg;	mdatasize = datasize; mtype = type;mopt = opt; mkeysize = keysize; mivsize = ivsize;

	mparm = kmalloc(sizeof(struct parm)*N_THREADS,GFP_KERNEL);

	mytime_init();
	time = 0;
	for(j=0; j<DO_NUM;j++) {

		for(i=0;i<N_THREADS;i++)
		{
			init_completion(&(mparm[i].w));
			init_completion(&(mparm[i].c));
		}

		for(i=0;i<N_THREADS;i++)
		{
			task[i] = kthread_create(sym_newapi_speed_do_asyn_recovery,(void *)(&(mparm[i])),"sym_speed");
			if(!IS_ERR(task[i]))
			{
				wake_up_process(task[i]);
			}
			else
			{
				return 0;
			}
		}

		wait_timeout_kcapi(100);

		tv = mytime_on();

		for(i=0;i<N_THREADS;i++)
		{
			complete(&(mparm[i].w));
		}
		for(i=0;i<N_THREADS;i++)
		{
			wait_for_completion_interruptible(&(mparm[i].c));
		}

		mytime_off(tv);
		time += mytime_c();
		mytime_init();
	}

	speed = DO_NUM*N_THREADS*mdatasize/time;
	speed*=8;
#ifdef ASYN_MODE_BENCHMARK
	printk(KERN_ERR "%s,size is %d,speed is %dMbps,%d\n",mstring,mdatasize,speed,time);
#else
	printk(KERN_ERR "%s function test done!\n",mstring);
#endif
	kfree(mparm);
	return 0;
}

int hash_newapi_speed(char *mstring,u8 alg,u8 type,u8 opt,int datasize,int keysize,int ivsize)
{

	struct parm *mparm;
	
	struct task_struct *task[N_THREADS];
	
	int i,time,speed;

	struct timespec tv;

	printk(KERN_ERR "%s speed test start\n",mstring);
	
	malg = alg;	mdatasize = datasize; mtype = type;mopt = opt; mkeysize = keysize; mivsize = ivsize;

	mparm = kmalloc(sizeof(struct parm)*N_THREADS,GFP_KERNEL);

	mytime_init();

	for(i=0;i<N_THREADS;i++)
	{
		init_completion(&(mparm[i].w));
		init_completion(&(mparm[i].c));
	}

	for(i=0;i<N_THREADS;i++)
	{
		task[i] = kthread_create(hash_newapi_speed_do,(void *)(&(mparm[i])),"hash_speed");
		if(!IS_ERR(task[i]))
		{
			wake_up_process(task[i]);
		}
		else
		{
			return 0;
		}
	}

	wait_timeout_kcapi(100);

	tv = mytime_on();

	for(i=0;i<N_THREADS;i++)
	{
		complete(&(mparm[i].w));
	}
	for(i=0;i<N_THREADS;i++)
	{
		wait_for_completion_interruptible(&(mparm[i].c));
	}

	mytime_off(tv);
	time = mytime_c();
	speed = DO_NUM*N_THREADS*mdatasize/time;
	speed*=8;
	printk(KERN_ERR "%s,size is %d,speed is %dMbps,%d\n",mstring,mdatasize,speed,time);
	kfree(mparm);
	return 0;
}

int hash_newapi_speed_asyn_recovery(char *mstring,u8 alg,u8 type,u8 opt,int datasize,int keysize,int ivsize)
{

	struct parm *mparm;
	
	struct task_struct *task[N_THREADS];
	
	int i,j;
	uint32_t time,speed;

	struct timespec tv;

	//printk(KERN_ERR "%s speed test start\n",mstring);
	
	malg = alg;	mdatasize = datasize; mtype = type;mopt = opt; mkeysize = keysize; mivsize = ivsize;

	mparm = kmalloc(sizeof(struct parm)*N_THREADS,GFP_KERNEL);

	mytime_init();
	time = 0;
	for(j=0; j<DO_NUM;j++) {

		for(i=0;i<N_THREADS;i++)
		{
			init_completion(&(mparm[i].w));
			init_completion(&(mparm[i].c));
		}

		for(i=0;i<N_THREADS;i++)
		{
			task[i] = kthread_create(hash_newapi_speed_do_asyn_recovery,(void *)(&(mparm[i])),"hash_speed");
			if(!IS_ERR(task[i]))
			{
				wake_up_process(task[i]);
			}
			else
			{
				return 0;
			}
		}

		wait_timeout_kcapi(100);

		tv = mytime_on();

		for(i=0;i<N_THREADS;i++)
		{
			complete(&(mparm[i].w));
		}
		for(i=0;i<N_THREADS;i++)
		{
			wait_for_completion_interruptible(&(mparm[i].c));
		}

		mytime_off(tv);
		time += mytime_c();
		mytime_init();
	}
	speed = DO_NUM*N_THREADS*mdatasize/time;
	speed*=8;
#ifdef ASYN_MODE_BENCHMARK
	printk(KERN_ERR "%s,size is %d,speed is %dMbps,%d\n",mstring,mdatasize,speed,time);
#else
	printk(KERN_ERR "%s function test done!\n",mstring);
#endif
	kfree(mparm);
	return 0;
}
void sym_speed_benchmark(int size)
{
	sym_newapi_speed("SM1 ECB ENC",SM1,ECB,ENC,size,32,16);
	sym_newapi_speed("SM1 ECB DEC",SM1,ECB,DEC,size,32,16);
	sym_newapi_speed("SM1 CBC ENC",SM1,CBC,ENC,size,32,16);
	sym_newapi_speed("SM1 CBC DEC",SM1,CBC,DEC,size,32,16);
	sym_newapi_speed("SM1 CFB ENC",SM1,CFB,ENC,size,32,16);
	sym_newapi_speed("SM1 CFB DEC",SM1,CFB,DEC,size,32,16);
	sym_newapi_speed("SM1 OFB ENC",SM1,OFB,ENC,size,32,16);
	sym_newapi_speed("SM1 OFB DEC",SM1,OFB,DEC,size,32,16);

	sym_newapi_speed("SM4 ECB ENC",SM4,ECB,ENC,size,16,16);
	sym_newapi_speed("SM4 ECB DEC",SM4,ECB,DEC,size,16,16);
	sym_newapi_speed("SM4 CBC ENC",SM4,CBC,ENC,size,16,16);
	sym_newapi_speed("SM4 CBC DEC",SM4,CBC,DEC,size,16,16);
	sym_newapi_speed("SM4 CFB ENC",SM4,CFB,ENC,size,16,16);
	sym_newapi_speed("SM4 CFB DEC",SM4,CFB,DEC,size,16,16);
	sym_newapi_speed("SM4 OFB ENC",SM4,OFB,ENC,size,16,16);
	sym_newapi_speed("SM4 OFB DEC",SM4,OFB,DEC,size,16,16);

	sym_newapi_speed("AES ECB ENC",AES,ECB,ENC,size,32,16);
	sym_newapi_speed("AES ECB DEC",AES,ECB,DEC,size,32,16);
	sym_newapi_speed("AES CBC ENC",AES,CBC,ENC,size,32,16);
	sym_newapi_speed("AES CBC DEC",AES,CBC,DEC,size,32,16);
	sym_newapi_speed("AES CFB ENC",AES,CFB,ENC,size,32,16);
	sym_newapi_speed("AES CFB DEC",AES,CFB,DEC,size,32,16);
	sym_newapi_speed("AES OFB ENC",AES,OFB,ENC,size,32,16);
	sym_newapi_speed("AES OFB DEC",AES,OFB,DEC,size,32,16);

	sym_newapi_speed("DES ECB ENC",DES,ECB,ENC,size,8,16);
	sym_newapi_speed("DES ECB DEC",DES,ECB,DEC,size,8,16);
	sym_newapi_speed("DES CBC ENC",DES,CBC,ENC,size,8,16);
	sym_newapi_speed("DES CBC DEC",DES,CBC,DEC,size,8,16);
	sym_newapi_speed("DES CFB ENC",DES,CFB,ENC,size,8,16);
	sym_newapi_speed("DES CFB DEC",DES,CFB,DEC,size,8,16);
	sym_newapi_speed("DES OFB ENC",DES,OFB,ENC,size,8,16);
	sym_newapi_speed("DES OFB DEC",DES,OFB,DEC,size,8,16);

	sym_newapi_speed("DES3 ECB ENC",DES3,ECB,ENC,size,24,16);
	sym_newapi_speed("DES3 ECB DEC",DES3,ECB,DEC,size,24,16);
	sym_newapi_speed("DES3 CBC ENC",DES3,CBC,ENC,size,24,16);
	sym_newapi_speed("DES3 CBC DEC",DES3,CBC,DEC,size,24,16);
	sym_newapi_speed("DES3 CFB ENC",DES3,CFB,ENC,size,24,16);
	sym_newapi_speed("DES3 CFB DEC",DES3,CFB,DEC,size,24,16);
	sym_newapi_speed("DES3 OFB ENC",DES3,OFB,ENC,size,24,16);
	sym_newapi_speed("DES3 OFB DEC",DES3,OFB,DEC,size,24,16);

	sym_newapi_speed("SSF33 ECB ENC",SSF33,ECB,ENC,size,16,16);
	sym_newapi_speed("SSF33 ECB DEC",SSF33,ECB,DEC,size,16,16);
	sym_newapi_speed("SSF33 CBC ENC",SSF33,CBC,ENC,size,16,16);
	sym_newapi_speed("SSF33 CBC DEC",SSF33,CBC,DEC,size,16,16);
	sym_newapi_speed("SSF33 CFB ENC",SSF33,CFB,ENC,size,16,16);
	sym_newapi_speed("SSF33 CFB DEC",SSF33,CFB,DEC,size,16,16);
	sym_newapi_speed("SSF33 OFB ENC",SSF33,OFB,ENC,size,16,16);
	sym_newapi_speed("SSF33 OFB DEC",SSF33,OFB,DEC,size,16,16);

	sym_newapi_speed("SM6 ECB ENC",SM6,ECB,ENC,size,32,16);
	sym_newapi_speed("SM6 ECB DEC",SM6,ECB,DEC,size,32,16);
	sym_newapi_speed("SM6 CBC ENC",SM6,CBC,ENC,size,32,16);
	sym_newapi_speed("SM6 CBC DEC",SM6,CBC,DEC,size,32,16);
	sym_newapi_speed("SM6 CFB ENC",SM6,CFB,ENC,size,32,16);
	sym_newapi_speed("SM6 CFB DEC",SM6,CFB,DEC,size,32,16);
	sym_newapi_speed("SM6 OFB ENC",SM6,OFB,ENC,size,32,16);
	sym_newapi_speed("SM6 OFB DEC",SM6,OFB,DEC,size,32,16);

}

void hash_speed_benchmark(int size)
{

	hash_newapi_speed("SM3 HASH ENC",SM3,T_HASH,ENC,size,32,32);
	hash_newapi_speed("SM3 HMAC ENC",SM3,T_HMAC,ENC,size,32,32);

	hash_newapi_speed("MD5 HASH ENC",MD5,T_HASH,ENC,size,16,16);
	hash_newapi_speed("MD5 HMAC ENC",MD5,T_HMAC,ENC,size,16,16);

	hash_newapi_speed("SHA0 HASH ENC",SHA0,T_HASH,ENC,size,20,32);
	hash_newapi_speed("SHA0 HMAC ENC",SHA0,T_HMAC,ENC,size,20,32);

	hash_newapi_speed("SHA1 HASH ENC",SHA1,T_HASH,ENC,size,20,32);
	hash_newapi_speed("SHA1 HMAC ENC",SHA1,T_HMAC,ENC,size,20,32);

	hash_newapi_speed("SHA224 HASH ENC",SHA224,T_HASH,ENC,size,28,32);
	hash_newapi_speed("SHA224 HMAC ENC",SHA224,T_HMAC,ENC,size,28,32);

	hash_newapi_speed("SHA256 HASH ENC",SHA256,T_HASH,ENC,size,32,32);
	hash_newapi_speed("SHA256 HMAC ENC",SHA256,T_HMAC,ENC,size,32,32);

	hash_newapi_speed("SHA384 HASH ENC",SHA384,T_HASH,ENC,size,48,64);
	hash_newapi_speed("SHA384 HMAC ENC",SHA384,T_HMAC,ENC,size,48,64);

	hash_newapi_speed("SHA512 HASH ENC",SHA512,T_HASH,ENC,size,64,64);
	hash_newapi_speed("SHA512 HMAC ENC",SHA512,T_HMAC,ENC,size,64,64);
}

void sym_speed_benchmark_asyn(int size)
{
	sym_newapi_speed_asyn_recovery("SM1 ECB ENC",SM1,ECB,ENC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM1 ECB DEC",SM1,ECB,DEC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM1 CBC ENC",SM1,CBC,ENC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM1 CBC DEC",SM1,CBC,DEC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM1 CFB ENC",SM1,CFB,ENC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM1 CFB DEC",SM1,CFB,DEC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM1 OFB ENC",SM1,OFB,ENC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM1 OFB DEC",SM1,OFB,DEC,size,32,16);

	sym_newapi_speed_asyn_recovery("SM4 ECB ENC",SM4,ECB,ENC,size,16,16);
	sym_newapi_speed_asyn_recovery("SM4 ECB DEC",SM4,ECB,DEC,size,16,16);
	sym_newapi_speed_asyn_recovery("SM4 CBC ENC",SM4,CBC,ENC,size,16,16);
	sym_newapi_speed_asyn_recovery("SM4 CBC DEC",SM4,CBC,DEC,size,16,16);
	sym_newapi_speed_asyn_recovery("SM4 CFB ENC",SM4,CFB,ENC,size,16,16);
	sym_newapi_speed_asyn_recovery("SM4 CFB DEC",SM4,CFB,DEC,size,16,16);
	sym_newapi_speed_asyn_recovery("SM4 OFB ENC",SM4,OFB,ENC,size,16,16);
	sym_newapi_speed_asyn_recovery("SM4 OFB DEC",SM4,OFB,DEC,size,16,16);

	sym_newapi_speed_asyn_recovery("AES ECB ENC",AES,ECB,ENC,size,32,16);
	sym_newapi_speed_asyn_recovery("AES ECB DEC",AES,ECB,DEC,size,32,16);
	sym_newapi_speed_asyn_recovery("AES CBC ENC",AES,CBC,ENC,size,32,16);
	sym_newapi_speed_asyn_recovery("AES CBC DEC",AES,CBC,DEC,size,32,16);
	sym_newapi_speed_asyn_recovery("AES CFB ENC",AES,CFB,ENC,size,32,16);
	sym_newapi_speed_asyn_recovery("AES CFB DEC",AES,CFB,DEC,size,32,16);
	sym_newapi_speed_asyn_recovery("AES OFB ENC",AES,OFB,ENC,size,32,16);
	sym_newapi_speed_asyn_recovery("AES OFB DEC",AES,OFB,DEC,size,32,16);

	sym_newapi_speed_asyn_recovery("DES ECB ENC",DES,ECB,ENC,size,8,16);
	sym_newapi_speed_asyn_recovery("DES ECB DEC",DES,ECB,DEC,size,8,16);
	sym_newapi_speed_asyn_recovery("DES CBC ENC",DES,CBC,ENC,size,8,16);
	sym_newapi_speed_asyn_recovery("DES CBC DEC",DES,CBC,DEC,size,8,16);
	sym_newapi_speed_asyn_recovery("DES CFB ENC",DES,CFB,ENC,size,8,16);
	sym_newapi_speed_asyn_recovery("DES CFB DEC",DES,CFB,DEC,size,8,16);
	sym_newapi_speed_asyn_recovery("DES OFB ENC",DES,OFB,ENC,size,8,16);
	sym_newapi_speed_asyn_recovery("DES OFB DEC",DES,OFB,DEC,size,8,16);

	sym_newapi_speed_asyn_recovery("DES3 ECB ENC",DES3,ECB,ENC,size,24,16);
	sym_newapi_speed_asyn_recovery("DES3 ECB DEC",DES3,ECB,DEC,size,24,16);
	sym_newapi_speed_asyn_recovery("DES3 CBC ENC",DES3,CBC,ENC,size,24,16);
	sym_newapi_speed_asyn_recovery("DES3 CBC DEC",DES3,CBC,DEC,size,24,16);
	sym_newapi_speed_asyn_recovery("DES3 CFB ENC",DES3,CFB,ENC,size,24,16);
	sym_newapi_speed_asyn_recovery("DES3 CFB DEC",DES3,CFB,DEC,size,24,16);
	sym_newapi_speed_asyn_recovery("DES3 OFB ENC",DES3,OFB,ENC,size,24,16);
	sym_newapi_speed_asyn_recovery("DES3 OFB DEC",DES3,OFB,DEC,size,24,16);

	sym_newapi_speed_asyn_recovery("SSF33 ECB ENC",SSF33,ECB,ENC,size,16,16);
	sym_newapi_speed_asyn_recovery("SSF33 ECB DEC",SSF33,ECB,DEC,size,16,16);
	sym_newapi_speed_asyn_recovery("SSF33 CBC ENC",SSF33,CBC,ENC,size,16,16);
	sym_newapi_speed_asyn_recovery("SSF33 CBC DEC",SSF33,CBC,DEC,size,16,16);
	sym_newapi_speed_asyn_recovery("SSF33 CFB ENC",SSF33,CFB,ENC,size,16,16);
	sym_newapi_speed_asyn_recovery("SSF33 CFB DEC",SSF33,CFB,DEC,size,16,16);
	sym_newapi_speed_asyn_recovery("SSF33 OFB ENC",SSF33,OFB,ENC,size,16,16);
	sym_newapi_speed_asyn_recovery("SSF33 OFB DEC",SSF33,OFB,DEC,size,16,16);

	sym_newapi_speed_asyn_recovery("SM6 ECB ENC",SM6,ECB,ENC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM6 ECB DEC",SM6,ECB,DEC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM6 CBC ENC",SM6,CBC,ENC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM6 CBC DEC",SM6,CBC,DEC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM6 CFB ENC",SM6,CFB,ENC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM6 CFB DEC",SM6,CFB,DEC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM6 OFB ENC",SM6,OFB,ENC,size,32,16);
	sym_newapi_speed_asyn_recovery("SM6 OFB DEC",SM6,OFB,DEC,size,32,16);
}

void hash_speed_benchmark_asyn(int size)
{
	hash_newapi_speed_asyn_recovery("SM3 HASH ENC",SM3,T_HASH,ENC,size,32,32);
	hash_newapi_speed_asyn_recovery("SM3 HMAC ENC",SM3,T_HMAC,ENC,size,32,32);

	hash_newapi_speed_asyn_recovery("MD5 HASH ENC",MD5,T_HASH,ENC,size,16,16);
	hash_newapi_speed_asyn_recovery("MD5 HMAC ENC",MD5,T_HMAC,ENC,size,16,16);

	hash_newapi_speed_asyn_recovery("SHA0 HASH ENC",SHA0,T_HASH,ENC,size,20,32);
	hash_newapi_speed_asyn_recovery("SHA0 HMAC ENC",SHA0,T_HMAC,ENC,size,20,32);

	hash_newapi_speed_asyn_recovery("SHA1 HASH ENC",SHA1,T_HASH,ENC,size,20,32);
	hash_newapi_speed_asyn_recovery("SHA1 HMAC ENC",SHA1,T_HMAC,ENC,size,20,32);

	hash_newapi_speed_asyn_recovery("SHA224 HASH ENC",SHA224,T_HASH,ENC,size,28,32);
	hash_newapi_speed_asyn_recovery("SHA224 HMAC ENC",SHA224,T_HMAC,ENC,size,28,32);

	hash_newapi_speed_asyn_recovery("SHA256 HASH ENC",SHA256,T_HASH,ENC,size,32,32);
	hash_newapi_speed_asyn_recovery("SHA256 HMAC ENC",SHA256,T_HMAC,ENC,size,32,32);

	hash_newapi_speed_asyn_recovery("SHA384 HASH ENC",SHA384,T_HASH,ENC,size,48,64);
	hash_newapi_speed_asyn_recovery("SHA384 HMAC ENC",SHA384,T_HMAC,ENC,size,48,64);

	hash_newapi_speed_asyn_recovery("SHA512 HASH ENC",SHA512,T_HASH,ENC,size,64,64);
	hash_newapi_speed_asyn_recovery("SHA512 HMAC ENC",SHA512,T_HMAC,ENC,size,64,64);

}

static int sym_benchmark(void)
{
	int i,size;

	printk(KERN_ERR "kcapi_custom_init: SYNC Mode Enabled!\n");
	
	sm1_stand_test();
	sm1_simple_test();
	sm3_stand_test();

	return 0;
	
	snoop_sp_sm1sm3_enc();
	snoop_sp_sm1sm3_dec();
	snoop_sp_sm4sm3_enc();
	snoop_sp_sm4sm3_dec();

	return 0;
	for(i=0;i<3;i++)
	{
		if(i==0)
			size = 0x40;
		if(i==1)
			size = 0x600;
		if(i==2)
			size = 0x10000;

		sym_speed_benchmark(size);
	}
	for(i=0;i<3;i++)
	{
		if(i==0)
			size = 0x40;					
		if(i==1)
			size = 0x600;
		if(i==2)
			size = 0x10000;

		hash_speed_benchmark(size);
	}

	for(i=0;i<3;i++)
	i=2;
	{
		if(i==0) size = 0x40;
		if(i==1) size = 0x600;
		if(i==2) size = 0x10000;
		snoop_sp_newapi_speed("SNOOP SP sm4 cbc sm4 hmac enc",SM4,CBC,ENC,size,16,16,H_SM3,T_HMAC,ENC,32,32);
	}
	return 0;
}

static int sym_benchmark_asyn(void)
{
	int i,size;
	unsigned int age_times = 0;
	printk(KERN_ERR "kcapi_custom_init: ASYN Mode Enabled!\n");

#ifndef ASYN_MODE_BENCHMARK
	// sm1_stand_test_asyn_recovery();
	// sm4_stand_test_asyn_recovery_key_in_ram();	
	// sm1_simple_test_asyn_recovery();
	// sm3_stand_test_asyn_recovery();
	// snoop_sp_sm4sm3_enc_asyn();
	// snoop_sp_sm4sm3_dec_asyn();
	// snoop_sp_sm1sm3_enc_asyn();
	// snoop_sp_sm1sm3_dec_asyn();
#endif

	for(i=0;i<3;i++)
	{
		if(i==0)
			size = 0x40;
		if(i==1)
			size = 0x600;
		if(i==2)
			size = 0x10000;

		sym_speed_benchmark_asyn(size);
	}
	for(i=0;i<3;i++)
	{
		if(i==0)
			size = 0x40;
		if(i==1)
			size = 0x600;
		if(i==2)
			size = 0x10000;

		hash_speed_benchmark_asyn(size);
	}
	for(i=0;i<3;i++)
	{
		if(i==0) size = 0x40;
		if(i==1) size = 0x600;
		if(i==2) size = 0x10000;

		snoop_sp_newapi_speed_asyn("SNOOP SP sm4 cbc sm3 hmac enc",SM4,CBC,ENC,size,16,16,H_SM3,T_HMAC,ENC,32,32);
		snoop_sp_newapi_speed_asyn("SNOOP SP sm4 cbc sm3 hmac dec",SM4,CBC,DEC,size,16,16,H_SM3,T_HMAC,DEC,32,32);
		snoop_sp_newapi_speed_asyn("SNOOP SP sm1 cbc sm3 hmac enc",SM1,CBC,ENC,size,32,16,H_SM3,T_HMAC,ENC,32,32);
		snoop_sp_newapi_speed_asyn("SNOOP SP sm1 cbc sm3 hmac dec",SM1,CBC,DEC,size,32,16,H_SM3,T_HMAC,DEC,32,32);
	}
	return 0;
}

static int __init kcapi_custom_init(void)
{
#ifndef ASYN_RESOURCE_RECOVERY
	sym_benchmark();
#else
	uint32_t times = 0;
	for(times = 0;times < 1;times++) 
	{
		//printk("SYM HASH Benchmark Aging Test, Run Times: %08d\n", times);
		sym_benchmark_asyn();
	}
#endif
	return 0;
}


static void __exit kcapi_custom_exit(void)
{	
	printk(KERN_INFO "kcapi_custom_exit: ended!\n");
}

module_init(kcapi_custom_init);
module_exit(kcapi_custom_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ccp903t custom api test");
MODULE_AUTHOR("zjjin@ccore.com");

